package service

import (
    "crypto/md5"
    "errors"
    "fmt"
    "strconv"
    
    "collecter/app/cache"
    "collecter/app/common/enum"
    "collecter/app/common/helper"
)

type Vcode struct {
    Event   string // 验证码事件：login、register、resetPassword、bindMoblie、bindEmail、accountActivate、others
    Account string // 账号：手机号 or email
}

var vcodeTemplates = map[string]string{
    "login":           "您本次登录的验证码是 %s，注意勿泄露给他人以免造成不必要损失！",
    "register":        "您在系统注册账号的验证码是 %s，注意勿泄露给他人以免造成不必要损失！",
    "resetPassword":   "您正在重置系统的登录密码，本次操作验证码是 %s，注意勿泄露给他人以免造成不必要损失！",
    "bindAccount":     "您正在执行账号绑定操作，本次操作验证码是 %s，注意勿泄露给他人以免造成不必要损失！",
    "accountActivate": "感谢您注册并将开始使用我们的系统及其相关的服务！\n您之所以收到这封邮件，是因为您在我们系统注册了账号，请点击下方链接进行账号激活。\n%s",
    "others":          "您本次操作的验证码是 %s，注意勿泄露给他人以免造成不必要损失！",
}

func NewVcode(account string, event string) *Vcode {
    return &Vcode{Account: account, Event: event}
}

//
// SendVcode
//  @Description: 发送验证码
//  @receiver v
//  @return error
//
//
// SendVcode
//  @Description: 发送验证码
//  @receiver v
//  @param args 需要特别指定发送的内容，而不是随机生成的随机数
//  @return error
//
func (v *Vcode) SendVcode(args ...string) error {
    if len(v.Event) == 0 {
        v.Event = "others"
    }
    var vcode string
    if len(args) > 0 {
        // 如果 args 参数传入的内容，则发送的内容直接使用传入的内容
        vcode = args[0]
    } else {
        vcode = strconv.Itoa(helper.GetRandNumber(1111, 999999))
    }
    cacheKey := v.getCacheKey()
    
    isMobile := helper.RegExpVerify(v.Account, "mobile")
    isEmail := helper.RegExpVerify(v.Account, "email")
    // fmt.Println(isMobile, isEmail)
    var res error
    if isMobile {
        vcode = "123456"
        res = v.sendSms(vcode)
    } else if isEmail {
        res = v.sendEmail(vcode)
    } else {
        return errors.New("发送验证码出错：账号格式错误")
    }
    if res != nil {
        return res
    }
    if err := cache.Cacher.Set(cacheKey, []byte(vcode), 600); err != nil {
        return err
    }
    return nil
}

//
// VerifyCode
//  @Description: 验证验证码
//  @receiver v
//  @param code 收到的验证码
//  @return error
//
func (v *Vcode) VerifyCode(code string) error {
    // if "dev" == helper.Configer.GetString("runmode") && len(code) > 0 {
    //     // 如果是开发环境并且验证码不为空，则直接跳过，不做实际的验证
    //     return nil
    // }
    // fmt.Printf("cacher: %+v\n", helper.Cacher)
    cacheKey := v.getCacheKey()
    if err := cache.Cacher.Has(cacheKey); err != nil {
        return errors.New("验证码错误")
    }
    vcode, err := cache.Cacher.Get(cacheKey)
    if err != nil {
        return err
    }
    if code != string(vcode) {
        return errors.New("验证码错误")
    }
    return nil
}

func (v *Vcode) sendSms(code string) error {
    return nil
}

func (v *Vcode) sendEmail(code string) error {
    toUser := make([]string, 0, 0)
    toUser = append(toUser, v.Account)
    subject := "验证码消息"
    content := vcodeTemplates[v.Event]
    content = fmt.Sprintf(content, code)
    
    email := NewEmail().
        WithToUsers(toUser).
        WithSbuject(subject).
        WithFormat("text").
        WithContent(content).
        WithAnnexs(nil)
    return email.SendEmail()
}

func (v *Vcode) getCacheKey() string {
    accountHash := md5.Sum([]byte(v.Account))
    cacheKey := enum.VCODE + v.Event + ":" + fmt.Sprintf("%x", accountHash)
    return cacheKey
}
